package com.weichen.studentgameexchange.gateway.filter;

import cn.hutool.core.util.StrUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.*;

@Component
public class JwtGatewayFilterFactory extends AbstractGatewayFilterFactory<JwtGatewayFilterFactory.Config> {


    @Autowired
    public JwtGatewayFilterFactory() {
        super(Config.class);
    }

    private static final List<String> ALLOWED_PATHS = Arrays.asList(
            "/login","/file/download/**", "/doc.html", "/webjars/**", "/swagger-ui/**", "/v3/api-docs/**"
    );

    @Override
    public List<String> shortcutFieldOrder() {
        return Collections.singletonList("tokenHeaderName");
    }

    public static class Config {
        private String tokenHeaderName = "Authorization";

        public Config() {
        }

        public String getTokenHeaderName() {
            return tokenHeaderName;
        }

        public void setTokenHeaderName(String tokenHeaderName) {
            this.tokenHeaderName = tokenHeaderName;
        }
    }

    @Override
    public GatewayFilter apply(Config config) {
        if (config == null) {
            throw new IllegalArgumentException("Config cannot be null");
        }
        final String finalTokenHeaderName = config.getTokenHeaderName();
        return (exchange, chain) -> {
            ServerHttpRequest request = exchange.getRequest();
            ServerHttpResponse response = exchange.getResponse();
            String path = request.getPath().toString();

            // 处理OPTIONS请求
            if (HttpMethod.OPTIONS.equals(request.getMethod())) {
                response.setStatusCode(HttpStatus.OK);
                response.getHeaders().add("Access-Control-Allow-Origin", "http://localhost:3000");
                response.getHeaders().add("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
                response.getHeaders().add("Access-Control-Allow-Headers", "Content-Type, " + finalTokenHeaderName);
                response.getHeaders().add("Access-Control-Allow-Credentials", "true");
                return response.setComplete();
            }

            for (String allowedPath : ALLOWED_PATHS) {
                if (path.matches(allowedPath.replace("/**", ".*"))) {
                    return chain.filter(exchange);
                }
            }

            String token = request.getHeaders().getFirst(finalTokenHeaderName);
            if (StrUtil.isBlank(token)) {
                return unauthorizedResponse(exchange, "请登录");
            }
                // 处理Bearer前缀
            if (token.startsWith("Bearer ")) {
                token = token.substring(7);
            }
            System.out.println("Token: " + token); // 打印Token
            try {
                Algorithm algorithm = Algorithm.HMAC256("H4FX3kR7rBr5lALVUhmbwsLDNj05+UgaqT25lbmFDjw=");
                JWTVerifier verifier = JWT.require(algorithm).withSubject("User").build();
                verifier.verify(token);
                System.out.println("Token验证通过"); // 打印验证结果
            } catch (JWTVerificationException e) {
                System.out.println("Token验证失败: " + e.getMessage()); // 打印失败原因
                return unauthorizedResponse(exchange, "无效的 Token");
            }

            return chain.filter(exchange);
        };
    }

    private Mono<Void> unauthorizedResponse(ServerWebExchange exchange, String message) {
        ServerHttpResponse response = exchange.getResponse();
        response.setStatusCode(HttpStatus.UNAUTHORIZED);
        response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");

        Map<String, Object> error = new HashMap<>();
        error.put("code", HttpStatus.UNAUTHORIZED.value());
        error.put("message", message);

        ObjectMapper objectMapper = new ObjectMapper();
        byte[] bytes = new byte[0];
        try {
            bytes = objectMapper.writeValueAsBytes(error);
        } catch (Exception e) {
            e.printStackTrace();
        }
        DataBuffer buffer = response.bufferFactory().wrap(bytes);
        return response.writeWith(Flux.just(buffer));
    }
}
